package cqrtplm.schedule;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hustcad.plm.pdm.doc.vo.DocDetails;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeValueService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartRelObjectService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartService;
import com.hustcad.plm.pdm.partbom.vo.TyPartAllVO;
import com.hustcad.plm.pdm.user.service.TyplmUserService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.entity.part.PartDO;
import com.ty.basic.session.TyAccountContext;
import com.ty.basic.vo.AttributeVO;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.dto.EncodedMasterDataDTO;
import cqrtplm.entity.MaterialSapSyncDO;
import cqrtplm.mapper.MaterialSapSyncMapper;
import cqrtplm.mapper.RTPartMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
@Slf4j
public class SendSapPartMasterSchedule {

    @Resource
    private RTPartMapper rtPartMapper;

    @Resource
    private MaterialSapSyncMapper materialSapSyncMapper;

    @Resource
    private TyplmPartService typlmPartService;

    @Resource
    private TyplmAttributeValueService typlmAttributeValueService;

    @Resource
    private TyplmPartRelObjectService typlmPartRelObjectService;

    @Resource
    private TyplmUserService typlmUserService;

    @Value("${sap.name}")
    private String sapName;

    @Value("${sap.password}")
    private String sapPassword;

    @Value("${sap.material.url}")
    private String materialSapUrl;

    /**
     * 凌晨一点执行
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void doTask() {
        UserDO user = TyAccountContext.getUser();
        log.info("开始执行发送物料SAP同步任务>>>>>>>>>{}",user != null ? user.getName() : "user空!");
        //切换管理员账号
        TyAccountContext.setUser(typlmUserService.queryUserByName("admin"));
        sendSapPart();
        TyAccountContext.setUser(user);
        log.info("发送物料SAP同步任务结束>>>>>>>>>");
    }

    /**
     * 每天晚上凌晨一点执行
     */
    public void sendSapPart() {
        List<MaterialSapSyncDO> materialSapSyncDOS = materialSapSyncMapper.selectYesterdayUnsentData();
        JSONObject jsonObject = new JSONObject();
        JSONArray array = new JSONArray();

        // 创建物料编码到主键的映射
        Map<String, String> partNumberToIdMap = new HashMap<>();
        for (MaterialSapSyncDO materialSapSyncDO : materialSapSyncDOS) {
            EncodedMasterDataDTO encodedMasterDataDTO = sendSapByPartNumber(materialSapSyncDO.getMaterialCode());
            if (encodedMasterDataDTO != null) {
                array.add(convertToUpperCaseJSONObject(encodedMasterDataDTO));
                partNumberToIdMap.put(materialSapSyncDO.getMaterialCode(), materialSapSyncDO.getId());
            }
        }

        JSONObject json = new JSONObject();
        json.put("item", array);
        jsonObject.put("IN_TAB", json);
        String msg = requestSAP(jsonObject);

        List<String> successPartNumberList = new ArrayList<>();

        if (StringUtils.isNotBlank(msg)) {
            JSONObject msgJSOBObject = JSONObject.parseObject(msg);
            if (msgJSOBObject.containsKey("OUT_TAB")) {
                msgJSOBObject = msgJSOBObject.getJSONObject("OUT_TAB");
                if (msgJSOBObject.containsKey("item")) {
                    JSONArray msgJSONArray = msgJSOBObject.getJSONArray("item");
                    for (int i = 0; i < msgJSONArray.size(); i++) {
                        JSONObject tempJson = msgJSONArray.getJSONObject(i);
                        String partNo = tempJson.getString("MATNR");
                        String msgty = tempJson.getString("MSGTY");
                        if ("S".equals(msgty) && StringUtils.isNotBlank(partNo)) {
                            successPartNumberList.add(partNo);
                        }
                    }
                }
            }
        }

        // 收集集成成功的数据，使用主键更新数据库中是否下发SAP为1
        if (CollUtil.isNotEmpty(successPartNumberList)) {
            List<MaterialSapSyncDO> updateList = new ArrayList<>();
            for (String partNumber : successPartNumberList) {
                // 通过物料编码找到对应的主键
                if (partNumberToIdMap.containsKey(partNumber)) {
                    String id = partNumberToIdMap.get(partNumber);
                    // 创建更新对象
                    MaterialSapSyncDO updateDO = new MaterialSapSyncDO();
                    updateDO.setId(id);
                    updateDO.setIsSendToSap("1"); // 设置为已下发
                    updateDO.setSendSapSuccess("1"); // 设置为下发成功
                    updateDO.setUpdateUser("system"); // 更新人
                    updateList.add(updateDO);
                }
            }
            // 批量更新
            if (CollUtil.isNotEmpty(updateList)) {
                materialSapSyncMapper.batchUpdateMaterialSapSync(updateList);
                log.info("成功更新下发SAP状态的记录数量: {}", updateList.size());
            }
            log.info("成功下发SAP的物料数量: {}, 物料编码列表: {}", successPartNumberList.size(),
                     successPartNumberList);
        }
    }

    public EncodedMasterDataDTO sendSapByPartNumber(String partNumber) {
        PartDO partDO = rtPartMapper.queryLatestPartByNumberAndView(partNumber, "Design", null);
        if (partDO == null) {
            return null;
        }
        BigInteger oid = partDO.getOid();
        TyPartAllVO tyPartAllVO = this.typlmPartService.queryPartAllVO(oid, TableTypeConstrant.TY_PART_OTYPE);
        List<DocDetails> docDetailsList = typlmPartRelObjectService.queryPartRelatedDocInfo(oid);
        Map<String, List<AttributeVO>> ibaValuePart = typlmAttributeValueService.getAttrValueTableByEntitys(
                Collections.singletonList(oid), TableTypeConstrant.TY_PART_OTYPE);
        List<AttributeVO> attributeVOS = ibaValuePart.get(oid.toString());
        Map<String, String> ibaMap = attributeVOS.stream()
            .collect(Collectors.toMap(
                    AttributeVO::getAttributeEnName,
                    AttributeVO::getAttributeValue,
                    (e1, e2) -> e1 // 如果有重复键，保留第一个值
            ));
        EncodedMasterDataDTO encodedMasterDataDTO = new EncodedMasterDataDTO();
        encodedMasterDataDTO.setMatnr(partNumber);           // 物料编码
        encodedMasterDataDTO.setMaktx(partDO.getName());                    // 物料名称
        String typeName = tyPartAllVO.getTypeotype();
        if ("ty.inteplm.part.CTyPart|Standard".equals(typeName)) {//标准件
            encodedMasterDataDTO.setMtart("Z003");                    // 物料类型
            encodedMasterDataDTO.setMtbez("标准件");                    // 物料类型描述
        } else if ("ty.inteplm.part.CTyPart|MaterialCode".equals(typeName)) {//物料码
            encodedMasterDataDTO.setMtart("Z002");                    // 物料类型
            encodedMasterDataDTO.setMtbez("零部件");                    // 物料类型描述
        }
        encodedMasterDataDTO.setMeins("PE");                    // 基本计量单位
        encodedMasterDataDTO.setBismt(ibaMap.getOrDefault("oldMaterialCode", ""));    // 旧物料号
        encodedMasterDataDTO.setGewei("KG");                    // 重量单位
        encodedMasterDataDTO.setVoleh("M3");                    // 体积单位
        if (CollUtil.isNotEmpty(docDetailsList)) {
            encodedMasterDataDTO.setZsjtz("Y");                    // 是否有图纸
        } else {
            encodedMasterDataDTO.setZsjtz("N");
        }
        encodedMasterDataDTO.setZjx(ibaMap.getOrDefault("productType", ""));                      // 机型
        encodedMasterDataDTO.setZkfl(ibaMap.getOrDefault("devCode", ""));                     // 开发令
        encodedMasterDataDTO.setZcplb("");                    // 成品类别
        encodedMasterDataDTO.setZmaktx(ibaMap.getOrDefault("00026", ""));                   // 物料长文本
        encodedMasterDataDTO.setZjxhb(ibaMap.getOrDefault("MechanicalEnvirCode", ""));                    // 机械环保代码
        encodedMasterDataDTO.setWerks(ibaMap.getOrDefault("factory", ""));                    // 工厂
        encodedMasterDataDTO.setZth(partNumber);                      // 图号
        encodedMasterDataDTO.setBeskz("");                    // 采购类型
        //        encodedMasterDataDTO.setZsfbb(""));                    // 是否半BOM
        //        encodedMasterDataDTO.setZbbsm("");                    // 半BOM说明
        //        encodedMasterDataDTO.setZyzcpm("");                   // 验证成品码
        //        encodedMasterDataDTO.setBrgew("");                    // 毛重
        //        encodedMasterDataDTO.setNtgew("");                    // 净重
        //        encodedMasterDataDTO.setGroes("");                    // 大小量纲(体积)
        return encodedMasterDataDTO;
    }


    /**
     * 将 EncodedMasterDataDTO 转换为 JSONObject，字段名转为大写
     *
     * @param encodedMasterDataDTO EncodedMasterDataDTO 对象
     * @return 包含大写字段名的 JSONObject
     */
    private JSONObject convertToUpperCaseJSONObject(EncodedMasterDataDTO encodedMasterDataDTO) {
        JSONObject jsonObject = new JSONObject();

        try {
            Field[] fields = EncodedMasterDataDTO.class.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String fieldName = field.getName().toUpperCase(); // 转换为大写
                Object fieldValue = field.get(encodedMasterDataDTO);

                // 处理 null 值，转换为 ""
                if (fieldValue == null) {
                    jsonObject.put(fieldName, "");
                } else {
                    jsonObject.put(fieldName, fieldValue);
                }
            }
        } catch (IllegalAccessException e) {
            log.error("转换 EncodedMasterDataDTO 为 JSONObject 失败", e);
        }

        return jsonObject;
    }


    private String requestSAP(JSONObject jsonObject) {
        String result = "";
        String auth = sapName + ":" + sapPassword;
        // 进行 Base64 编码
        String encodedAuth = Base64.encode(auth);
        // 构建 Authorization 请求头的值
        String authHeader = "Basic " + encodedAuth;
        HttpResponse response = HttpRequest.post(materialSapUrl).header("Content-Type", "application/json").header(
                        "Authorization", authHeader) // 添加 Basic 认证头
                .body(JSON.toJSONString(jsonObject)).execute();
        // 处理响应
        if (response.isOk()) {
            result = response.body();
            log.info("请求成功，响应结果：{}", result);
        } else {
            log.error("请求失败，状态码：{}", response.getStatus());
            log.error("请求失败，失败原因：{}", response.body());
            throw RTErrorCodeEnum.SEND_SAP_EXCEPTION.getException("下发sap失败");
        }
        return result;
    }


}
